
package nccloud.arap.aggmanualcostvo.util.tool;

import nc.impl.pubapp.pattern.database.DataAccessUtils;
import nc.md.MDBaseQueryFacade;
import nc.md.model.IBean;
import nc.md.model.MetaDataException;
import nc.ui.querytemplate.querytree.IQueryScheme;
import nc.vo.bd.config.BDModeSelectedVO;
import nc.vo.bd.pub.NODE_TYPE;
import nc.vo.pub.BusinessException;
import nc.vo.pub.SuperVO;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.data.IRowSet;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.pubapp.query2.sql.process.QueryCondition;
import nc.vo.pubapp.query2.sql.process.QuerySchemeProcessor;
import nc.vo.uif2.LoginContext;
import nc.vo.util.BDModeManager;
import nc.vo.util.VisibleUtil;
import nccloud.commons.lang.StringUtils;

/**
* 基于管控模式的查询（适用于主子表结构）
*
* @since 6.0
* @version 2012-10-22 上午08:53:49
* @author fengjqc
*/
public class PURPFileManageModeQuery<E extends SuperVO> {
    private E headvo;
    private final static String PK_ORG = "pk_org";

    private Class<E> voclass;

    /**
    * @param voclass 注入管控模式的类（一般为表头）
    */
    public PURPFileManageModeQuery(Class<E> voclass) {
        this.voclass = voclass;
    }

    private static String split(String str) {
        if (str == null) {
            return null;
        }
        int begin = str.indexOf("(");
        int end = str.indexOf(")");
        if (begin < 0 || end < 0 || end <= begin) {
            return null;
        }
        return str.substring(begin + 1, end);
    }

    /**
    * @param selfwhere 补充的查询条件：包括查询模板上的条件，以及自定义的条件
    * @param context
    * @return
    */
    public String[] queryBillKeys(String selfwhere, LoginContext context) {
        SqlBuilder billKeysSql = new SqlBuilder();
        billKeysSql.append("select " + FileRuleTool.getPKFiled(this.getHeadVO()));

        // 补充的查询条件为空
        if (StringUtils.isBlank(selfwhere)) {
            billKeysSql.append(" from " + FileRuleTool.getTableName(this.getHeadVO()) + " where dr=0 ");
        }
        // 补充的查询条件不为空
        else {
            billKeysSql.append(selfwhere);
        }

        if (this.isManagerMode()) {
            billKeysSql.append(" and ");
            // 根据管控模式的可见性，获取管控下可见的内容
            try {
                billKeysSql.append(VisibleUtil.getVisibleCondition(context, this.voclass));
            } catch (BusinessException e) {
                ExceptionUtils.wrappException(e);
            }
        }

        DataAccessUtils utils = new DataAccessUtils();
        IRowSet rowset = utils.query(billKeysSql.toString());
        return rowset.toOneDimensionStringArray();
    }

    /**
    * 查询模板(此方法监测方案、抽样计划表、检测依据会调用，用于解决查询时根据用户选择的组织进行管控模式处理;检测依据不需要管控)
    *
    * @param context
    * @param queryScheme
    * @param patchwhere  补充查询条件，若没有patchwhere=null
    * @return
    */
    public String[] queryBillKeysByQueryScheme(IQueryScheme queryScheme, String patchwhere) {
        QuerySchemeProcessor processor = new QuerySchemeProcessor(queryScheme);
        String tablename = processor.getMainTableAlias();

        StringBuilder sqlBuilder = new StringBuilder();
        sqlBuilder.append(" select " + tablename + "." + FileRuleTool.getPKFiled(this.getHeadVO()));

        processor.appendWhere(" and " + tablename + ".dr = 0 ");

        if (!StringUtils.isBlank(patchwhere)) {
            processor.appendWhere(patchwhere);
        }
        //processor.appendCurrentGroup();//将当前集团加入当sql中，由二开自己选择是否加入
        sqlBuilder.append(processor.getFinalFromWhere());
        DataAccessUtils utils = new DataAccessUtils();
        String finaSql = sqlBuilder.toString();
        // 1.构造管控模式的where片段
        String mdWhere = this.constructMdWhere(tablename, processor);
        if (!StringUtils.isEmpty(mdWhere)) {
            // 根据用户有没有选择组织来确定当前是集团节点还是组织节点
            if (processor.getQueryCondition(PK_ORG) != null) {
                // 组织节点肯定必须唯一，此处不再判断
                QueryCondition orgCond = processor.getQueryCondition(PK_ORG);
                String pk_org = orgCond.getValues()[0];

                // 2.把最终的sql中的查询对话框所拼接的pk_org替换为上面的管控sql片段
                int begin = finaSql.indexOf(tablename + ".pk_org");
                int end = finaSql.indexOf(pk_org, begin) + pk_org.length() + 1;
                String oldChar = finaSql.substring(begin, end);
                finaSql = finaSql.replace(oldChar, mdWhere);
            } else {
                // 集团节点需要最近管控片段，pk_org='集团'
                finaSql += " and " + mdWhere;
            }
        }
        IRowSet rowset = utils.query(finaSql);
        return rowset.toOneDimensionStringArray();
    }

    /**
    * 查询模板 不基于管控模式
    *
    * @param queryScheme
    * @param patchwhere  补充查询条件，若没有patchwhere=null
    * @return
    */
    public String[] queryBillKeysByScheme(IQueryScheme queryScheme, String patchwhere) {
        QuerySchemeProcessor processor = new QuerySchemeProcessor(queryScheme);
        String tablename = processor.getMainTableAlias();

        StringBuilder sqlBuilder = new StringBuilder();
        sqlBuilder.append(" select " + tablename + "." + FileRuleTool.getPKFiled(this.getHeadVO()));

        processor.appendWhere(" and " + tablename + ".dr = 0 ");

        if (!StringUtils.isBlank(patchwhere)) {
            processor.appendWhere(patchwhere);
        }

        processor.appendCurrentGroup();
        sqlBuilder.append(processor.getFinalFromWhere());
        DataAccessUtils utils = new DataAccessUtils();
        IRowSet rowset = utils.query(sqlBuilder.toString());
        return rowset.toOneDimensionStringArray();
    }

    private String constructMdWhere(String tablename, QuerySchemeProcessor processor) {
        if (!this.isManagerMode()) {
            // 不是管控模式的档案不需处理,选择条件中没有选择组织的不需要处理管控
            return null;
        }
        // 1、从queryScheme中拿出所选择的pk_org值
        String org = null;
        QueryCondition cond = processor.getQueryCondition(PK_ORG);
        if (cond != null && cond.getValues() != null && cond.getValues().length == 1) {
            org = cond.getValues()[0];
        }
        try {
            // 2、调用VisibleUtil.getVisibleCondition获得管控sql片段
            String group = AppContext.getInstance().getPkGroup();
            String clname = this.voclass.getName();
            IBean bn = MDBaseQueryFacade.getInstance().getBeanByFullClassName(clname);
            String where = VisibleUtil.getVisibleCondition(org, group, NODE_TYPE.ORG_NODE, bn.getID());
            where = PURPFileManageModeQuery.split(where);
            return tablename + "." + where;
        } catch (Exception e1) {
            ExceptionUtils.wrappException(e1);
        }
        return null;
    }

    /**
    * 获取表头vo
    *
    * @return
    */
    private SuperVO getHeadVO() {
        if (null == this.headvo) {
            try {
                this.headvo = this.voclass.newInstance();
            } catch (InstantiationException ex) {
                ExceptionUtils.wrappException(ex);
            } catch (IllegalAccessException exp) {
                ExceptionUtils.wrappException(exp);
            }
        }
        return this.headvo;
    }

    /**
    * 是否基于管控模式管理
    *
    * @param clz
    * @return
    */
    private boolean isManagerMode() {
        try {
            IBean ibean = MDBaseQueryFacade.getInstance().getBeanByFullClassName(this.voclass.getName());
            BDModeSelectedVO vo = BDModeManager.getInstance().getBDModeSelectedVOByMDClassID(ibean.getID());
            if (vo != null) {
                return true;
            }
        } catch (MetaDataException e) {
             String message = nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common",
                "140050000-0024")/* @res "获取是否有管控模式时发生异常，作为没有管控模式处理" */;
             ExceptionUtils.wrappBusinessException(message);
        }
         return false;
    }

}
